package tools

import (
	"bytes"
	"crypto/aes"
	"crypto/cipher"
	"crypto/md5"
	"crypto/sha1"
	"crypto/sha256"
	//"encoding/base64"
	"encoding/hex"
	//"encoding/json"
	"fmt"
	"io/ioutil"
	"math/rand"
	"reflect"
	"regexp"
	"strconv"
	"strings"
	"time"
)

func MD5(str string) string {
	has := md5.Sum([]byte(str))
	md5str := fmt.Sprintf("%x", has)
	return md5str
}

func Md5SumFile(file string) (value [md5.Size]byte, err error) {
	data, err := ioutil.ReadFile(file)
	if err != nil {
		return
	}
	value = md5.Sum(data)
	return
}

func GeneralToken() string {
	token := Hash256(fmt.Sprintf("%d%d", time.Now().Unix(), rand.Int31()))
	if !FilteredSQLInject(token) {
		return token
	}
	return GeneralToken()
}

func Hash256(data string) string {
	hash := sha256.New()
	hash.Write([]byte(data))
	sum := hash.Sum(nil)
	return hex.EncodeToString(sum)
}

func Hash1(data string) string {
	hash := sha1.New()
	hash.Write([]byte(data))
	sum := hash.Sum(nil)
	return hex.EncodeToString(sum)
}



func AesDecrypt(crypted, key, iv []byte) ([]byte, error) {
	block, err := aes.NewCipher(key)
	if err != nil {
		return nil, err
	}
	//blockSize := block.BlockSize()
	blockMode := cipher.NewCBCDecrypter(block, iv)
	origData := make([]byte, len(crypted))
	blockMode.CryptBlocks(origData, crypted)
	//获取的数据尾端有'/x0e'占位符,去除它
	for i, ch := range origData {
		if ch == '\x0e' {
			origData[i] = ' '
		}
	}
	//{"phoneNumber":"15082726017","purePhoneNumber":"15082726017","countryCode":"86","watermark":{"timestamp":1539657521,"appid":"wx4c6c3ed14736228c"}}<nil>
	return origData, nil
}

func WriteSqlStr(buf *bytes.Buffer, a ...interface{}) {
	str := buf.String()
	if len(str) > 0 && str[len(str)-1] != ',' {
		buf.WriteString(" ,")
	}
	for _, v := range a {
		typeOf := reflect.TypeOf(v)
		if typeOf.String() == "string" {
			//buf.WriteString("'")
			if strings.Contains(v.(string), "=") {
				buf.WriteString(v.(string))
				continue
			}
			buf.WriteString("'")
			buf.WriteString(v.(string))
			buf.WriteString("'")
		} else if typeOf.String() == "int" {
			buf.WriteString(strconv.Itoa(v.(int)))
		} else if typeOf.String() == "int32" {
			buf.WriteString(strconv.Itoa(int(v.(int32))))
		} else if typeOf.String() == "int64" {
			buf.WriteString(strconv.Itoa(int(v.(int64))))
		}
	}
}

func MyAbc(n int) int {
	if n < 0 {
		return -n
	}
	return n
}

var (
	Day   = 24 * time.Hour
	Month = 31 * Day
	Year  = 365.13 * float32(Day)
)

//大约输出
//rule: 1d=24h 1m=31d  1y=365.13d
func SecondsToYearMonthDay(seconds time.Duration) (year, month, day time.Duration) {
	year = seconds / time.Duration(Year)
	nmonth := seconds % time.Duration(Year)
	month = nmonth / Month
	nday := nmonth % Month
	day = nday / Day
	return
}

//retrun format 2006-01-02 15:04:05
func FormatTimeStandard(t time.Time) string {
	return t.Format("2006-01-02 15:04:05")
}

//func MgoDataTimeToGOTime(dt interface{}) time.Time {
//	return time.Unix(int64(dt.(primitive.DateTime))/1000, 0)
//}

func Duplicate(a interface{}) (ret []interface{}) {
	va := reflect.ValueOf(a)
	for i := 0; i < va.Len(); i++ {
		if i > 0 && reflect.DeepEqual(va.Index(i-1).Interface(), va.Index(i).Interface()) {
			continue
		}
		ret = append(ret, va.Index(i).Interface())
	}
	return ret
}

func CalculationSpend(t time.Time, now time.Time) int64 {
	fmt.Println("star %s end %s", FormatTimeStandard(t), FormatTimeStandard(now))
	return (now.UnixNano() / 1e6) - (t.UnixNano() / 1e6)
}

func ContainsRange(str string, min, max int) bool {
	arr := strings.Split(str, ",")
	for _, v := range arr {
		if v == " " {
			if len(arr) == 1 {
				return false
			}
			continue
		}
		n, _ := strconv.Atoi(v)
		if min > n {
			return false
		}
		if max < n {
			return false
		}
	}
	return true
}

func RemoveRepeatedElement(arr []string) (newArr []string, repeatArr []string) {
	newArr = make([]string, 0)
	repeatArr = make([]string, 0)
	for i := 0; i < len(arr); i++ {
		repeat := false
		for j := i + 1; j < len(arr); j++ {
			if arr[i] == arr[j] {
				repeat = true
				break
			}
		}
		if !repeat {
			newArr = append(newArr, arr[i])
		} else {
			repeatArr = append(repeatArr, arr[i])
		}
	}
	return
}

func Compare(arr []string, subArr []string) (sameArr, notSameArr []string) {
	sameArr = make([]string, 0)
	notSameArr = make([]string, 0)
	for i := range arr {
		var isSame bool
		for j := range subArr {
			if arr[i] == subArr[j] {
				isSame = true
				break
			}
		}
		if isSame {
			sameArr = append(sameArr, arr[i])
		} else {
			notSameArr = append(notSameArr, arr[i])
		}
	}
	return
}

func CompareNumRange(n, min, max int) bool {
	if n < min || n > max {
		return false
	}
	return true
}

var monthM = map[string]int{
	"January":   1,
	"February":  2,
	"March":     3,
	"April":     4,
	"May":       5,
	"June":      6,
	"July":      7,
	"August":    8,
	"September": 9,
	"October":   10,
	"November":  11,
	"December":  12,
}

func MonthTransfNum(month string) int {
	return monthM[month]
}

func TrimHTMLElements(str string) (result string, err error) {
	if str == "" {
		return "", nil
	}

	var compile *regexp.Regexp
	compile, err = regexp.Compile(`(<{0,1}em>)|(<em>{0,1})|(<{0,1}\/em>{0,1})`)
	if err != nil {
		return "", err
	}
	if !compile.MatchString(str) {
		result = str
		return
	}
	result = compile.ReplaceAllString(str, "")
	return TrimHTMLElements(result)
}

func DecimalKeepN(str string, n int) string {
	if n < 1 {
		n = -1 //取整
	}
	if strings.Contains(str, ".") {
		index := strings.Index(str, ".") + 1
		if len(str[index:]) < n {
			return str
		} else {
			return str[:index+n]
		}
	}
	return str
}

func DecimalKeep0(str string) string {
	return DecimalKeepN(str, 0)
}

func DecimalKeep1(str string) string {
	return DecimalKeepN(str, 1)
}

func DecimalKeep2(str string) string {
	return DecimalKeepN(str, 2)
}

func GetUserAgeByBirthday(birthday string) (age int, err error) {
	birthdayTime, err := time.Parse("2006-01-02", birthday)
	if err != nil {
		return
	}
	age1, _, _ := SecondsToYearMonthDay(time.Now().Sub(birthdayTime))
	age = int(age1)
	return
}

func IsSameDay(t1 time.Time, t2 time.Time) bool {
	return t1.Year() == t2.Year() && t1.Month() == t2.Month() && t1.Day() == t2.Day()
}

func GetVideoUrlByVideoObjStr(video string) string {
	split := strings.Split(video, `{"video":"`)
	fmt.Println(len(split), split)
	s := strings.Split(split[1], `","`)
	return s[0]
}
